

<!DOCTYPE html>
<html lang="zh-CN" data-default-color-scheme=auto>



<head>
  <meta charset="UTF-8">
  <link rel="apple-touch-icon" sizes="76x76" href="/blog/img/maple_leaf.png">
  <link rel="icon" href="/blog/img/maple_leaf.png">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, shrink-to-fit=no">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  
  <meta name="theme-color" content="#2f4154">
  <meta name="author" content="枫🍁川">
  <meta name="keywords" content="">
  
    <meta name="description" content="resolve和reject咱们来看一段Promise的代码： let p1 &#x3D; new Promise((resolve, reject) &#x3D;&gt; &amp;#123;     resolve(&amp;#x27;成功&amp;#x27;)     reject(&amp;#x27;失败&amp;#x27;) &amp;#125;) console.log(&amp;#x27;p1&amp;#x27;, p1)  let p2 &#x3D; new Promise">
<meta property="og:type" content="article">
<meta property="og:title" content="手写 Promise">
<meta property="og:url" content="https://destiny-yyc.github.io/promise-write.html">
<meta property="og:site_name" content="枫🍁川的博客">
<meta property="og:description" content="resolve和reject咱们来看一段Promise的代码： let p1 &#x3D; new Promise((resolve, reject) &#x3D;&gt; &amp;#123;     resolve(&amp;#x27;成功&amp;#x27;)     reject(&amp;#x27;失败&amp;#x27;) &amp;#125;) console.log(&amp;#x27;p1&amp;#x27;, p1)  let p2 &#x3D; new Promise">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/db87e7956fa24650bb60902bc3f113b4~tplv-k3u1fbpfcp-zoom-in-crop-mark:4536:0:0:0.awebp">
<meta property="og:image" content="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2c9636d819ef4bc78af95fb80c9a7be4~tplv-k3u1fbpfcp-zoom-in-crop-mark:4536:0:0:0.awebp">
<meta property="og:image" content="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/fa2e17b24a124dadba540e86350f1302~tplv-k3u1fbpfcp-zoom-in-crop-mark:4536:0:0:0.awebp">
<meta property="og:image" content="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/6ba5a2544b1144548cdc63362fa27d23~tplv-k3u1fbpfcp-zoom-in-crop-mark:4536:0:0:0.awebp">
<meta property="og:image" content="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/62a3c3afcf0a4262a1a7e52231c34dbc~tplv-k3u1fbpfcp-zoom-in-crop-mark:4536:0:0:0.awebp">
<meta property="article:published_time" content="2022-07-11T16:00:00.000Z">
<meta property="article:modified_time" content="2023-03-23T07:07:00.133Z">
<meta property="article:author" content="枫🍁川">
<meta property="article:tag" content="promise">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:image" content="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/db87e7956fa24650bb60902bc3f113b4~tplv-k3u1fbpfcp-zoom-in-crop-mark:4536:0:0:0.awebp">
  
  
    <meta name="referrer" content="no-referrer-when-downgrade">
  
  
  <title>手写 Promise - 枫🍁川的博客</title>

  <link  rel="stylesheet" href="https://lib.baomitu.com/twitter-bootstrap/4.6.1/css/bootstrap.min.css" />



  <link  rel="stylesheet" href="https://lib.baomitu.com/github-markdown-css/4.0.0/github-markdown.min.css" />

  <link  rel="stylesheet" href="https://lib.baomitu.com/hint.css/2.7.0/hint.min.css" />

  <link  rel="stylesheet" href="https://lib.baomitu.com/fancybox/3.5.7/jquery.fancybox.min.css" />



<!-- 主题依赖的图标库，不要自行修改 -->
<!-- Do not modify the link that theme dependent icons -->

<link rel="stylesheet" href="//at.alicdn.com/t/font_1749284_hj8rtnfg7um.css">



<link rel="stylesheet" href="//at.alicdn.com/t/font_1736178_lbnruvf0jn.css">


<link  rel="stylesheet" href="/blog/css/main.css" />


  <link id="highlight-css" rel="stylesheet" href="/blog/css/highlight.css" />
  
    <link id="highlight-css-dark" rel="stylesheet" href="/blog/css/highlight-dark.css" />
  




  <script id="fluid-configs">
    var Fluid = window.Fluid || {};
    Fluid.ctx = Object.assign({}, Fluid.ctx)
    var CONFIG = {"hostname":"destiny-yyc.github.io","root":"/blog/","version":"1.9.2","typing":{"enable":true,"typeSpeed":70,"cursorChar":"_","loop":false,"scope":[]},"anchorjs":{"enable":true,"element":"h1,h2,h3,h4,h5,h6","placement":"left","visible":"hover","icon":""},"progressbar":{"enable":true,"height_px":3,"color":"#29d","options":{"showSpinner":false,"trickleSpeed":100}},"code_language":{"enable":true,"default":"TEXT"},"copy_btn":true,"image_caption":{"enable":true},"image_zoom":{"enable":true,"img_url_replace":["",""]},"toc":{"enable":true,"placement":"right","headingSelector":"h1,h2,h3,h4,h5,h6","collapseDepth":0},"lazyload":{"enable":true,"loading_img":"/img/loading.gif","onlypost":false,"offset_factor":2},"web_analytics":{"enable":false,"follow_dnt":true,"baidu":null,"google":null,"gtag":null,"tencent":{"sid":null,"cid":null},"woyaola":null,"cnzz":null,"leancloud":{"app_id":null,"app_key":null,"server_url":null,"path":"window.location.pathname","ignore_local":false}},"search_path":"/blog/local-search.xml"};

    if (CONFIG.web_analytics.follow_dnt) {
      var dntVal = navigator.doNotTrack || window.doNotTrack || navigator.msDoNotTrack;
      Fluid.ctx.dnt = dntVal && (dntVal.startsWith('1') || dntVal.startsWith('yes') || dntVal.startsWith('on'));
    }
  </script>
  <script  src="/blog/js/utils.js" ></script>
  <script  src="/blog/js/color-schema.js" ></script>
  


  
<meta name="generator" content="Hexo 6.2.0"></head>


<body>
  

  <header>
    

<div class="header-inner" style="height: 70vh;">
  <nav id="navbar" class="navbar fixed-top  navbar-expand-lg navbar-dark scrolling-navbar">
  <div class="container">
    <a class="navbar-brand" href="/blog/">
      <strong>枫🍁川的博客</strong>
    </a>

    <button id="navbar-toggler-btn" class="navbar-toggler" type="button" data-toggle="collapse"
            data-target="#navbarSupportedContent"
            aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <div class="animated-icon"><span></span><span></span><span></span></div>
    </button>

    <!-- Collapsible content -->
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav ml-auto text-center">
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/blog/archives/">
                <i class="iconfont icon-archive-fill"></i>
                归档
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/blog/categories/">
                <i class="iconfont icon-category-fill"></i>
                分类
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/blog/tags/">
                <i class="iconfont icon-tags-fill"></i>
                标签
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/blog/about/">
                <i class="iconfont icon-user-fill"></i>
                关于
              </a>
            </li>
          
        
        
          <li class="nav-item" id="search-btn">
            <a class="nav-link" target="_self" href="javascript:;" data-toggle="modal" data-target="#modalSearch" aria-label="Search">
              &nbsp;<i class="iconfont icon-search"></i>&nbsp;
            </a>
          </li>
          
        
        
          <li class="nav-item" id="color-toggle-btn">
            <a class="nav-link" target="_self" href="javascript:;" aria-label="Color Toggle">&nbsp;<i
                class="iconfont icon-dark" id="color-toggle-icon"></i>&nbsp;</a>
          </li>
        
      </ul>
    </div>
  </div>
</nav>

  

<div id="banner" class="banner" parallax=true
     style="background: url('/blog/img/default.png') no-repeat center center; background-size: cover;">
  <div class="full-bg-img">
    <div class="mask flex-center" style="background-color: rgba(0, 0, 0, 0.3)">
      <div class="banner-text text-center fade-in-up">
        <div class="h2">
          
            <span id="subtitle" data-typed-text="手写 Promise"></span>
          
        </div>

        
          
  <div class="mt-3">
    
      <span class="post-meta mr-2">
        <i class="iconfont icon-author" aria-hidden="true"></i>
        枫🍁川
      </span>
    
    
      <span class="post-meta">
        <i class="iconfont icon-date-fill" aria-hidden="true"></i>
        <time datetime="2022-07-12 00:00" pubdate>
          2022年7月12日
        </time>
      </span>
    
  </div>

  <div class="mt-1">
    
      <span class="post-meta mr-2">
        <i class="iconfont icon-chart"></i>
        
          12k 字
        
      </span>
    

    

    
    
  </div>


        
      </div>

      
    </div>
  </div>
</div>

</div>

  </header>

  <main>
    
      

<div class="container-fluid nopadding-x">
  <div class="row nomargin-x">
    <div class="side-col d-none d-lg-block col-lg-2">
      

    </div>

    <div class="col-lg-8 nopadding-x-md">
      <div class="container nopadding-x-md" id="board-ctn">
        <div id="board">
          <article class="post-content mx-auto">
            <!-- SEO header -->
            <h1 style="display: none">手写 Promise</h1>
            
            
              <div class="markdown-body">
                
                <h2 id="resolve和reject"><a href="#resolve和reject" class="headerlink" title="resolve和reject"></a>resolve和reject</h2><p>咱们来看一段Promise的代码：</p>
<div class="code-wrapper"><pre><code class="hljs javascript"><span class="hljs-keyword">let</span> p1 = <span class="hljs-keyword">new</span> <span class="hljs-title class_">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> &#123;
    <span class="hljs-title function_">resolve</span>(<span class="hljs-string">&#x27;成功&#x27;</span>)
    <span class="hljs-title function_">reject</span>(<span class="hljs-string">&#x27;失败&#x27;</span>)
&#125;)
<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&#x27;p1&#x27;</span>, p1)

<span class="hljs-keyword">let</span> p2 = <span class="hljs-keyword">new</span> <span class="hljs-title class_">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> &#123;
    <span class="hljs-title function_">reject</span>(<span class="hljs-string">&#x27;失败&#x27;</span>)
    <span class="hljs-title function_">resolve</span>(<span class="hljs-string">&#x27;成功&#x27;</span>)
&#125;)
<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&#x27;p2&#x27;</span>, p2)

<span class="hljs-keyword">let</span> p3 = <span class="hljs-keyword">new</span> <span class="hljs-title class_">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> &#123;
    <span class="hljs-keyword">throw</span>(<span class="hljs-string">&#x27;报错&#x27;</span>)
&#125;)
<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&#x27;p3&#x27;</span>, p3)</code></pre></div>

<p>那么会输出什么呢？请看：</p>
<p><img src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/db87e7956fa24650bb60902bc3f113b4~tplv-k3u1fbpfcp-zoom-in-crop-mark:4536:0:0:0.awebp" srcset="/blog/img/loading.gif" lazyload></p>
<p><strong>这里暴露出了四个知识点：</strong></p>
<ul>
<li>1、执行了<code>resolve</code>，Promise状态会变成<code>fulfilled</code></li>
<li>2、执行了<code>reject</code>，Promise状态会变成<code>rejected</code></li>
<li>3、Promise只以<code>第一次为准</code>，第一次成功就<code>永久</code>为<code>fulfilled</code>，第一次失败就永远状态为<code>rejected</code></li>
<li>4、Promise中有<code>throw</code>的话，就相当于执行了<code>reject</code> 那么咱们就把这四个知识点一步步实现吧！！！</li>
</ul>
<h3 id="1、实现resolve与reject"><a href="#1、实现resolve与reject" class="headerlink" title="1、实现resolve与reject"></a>1、实现resolve与reject</h3><p>大家要注意：Promise的初始状态是<code>pending</code></p>
<p>这里很重要的一步是<code>resolve和reject的绑定this</code>，为什么要绑定<code>this</code>呢？这是为了resolve和reject的<code>this指向</code>永远指向当前的<code>MyPromise实例</code>，防止随着函数执行环境的改变而改变</p>
<div class="code-wrapper"><pre><code class="hljs javascript"><span class="hljs-keyword">class</span> <span class="hljs-title class_">MyPromise</span> &#123;
    <span class="hljs-comment">// 构造方法</span>
    <span class="hljs-title function_">constructor</span>(<span class="hljs-params">executor</span>) &#123;

        <span class="hljs-comment">// 初始化值</span>
        <span class="hljs-variable language_">this</span>.<span class="hljs-title function_">initValue</span>()
        <span class="hljs-comment">// 初始化this指向</span>
        <span class="hljs-variable language_">this</span>.<span class="hljs-title function_">initBind</span>()
        <span class="hljs-comment">// 执行传进来的函数</span>
        <span class="hljs-title function_">executor</span>(<span class="hljs-variable language_">this</span>.<span class="hljs-property">resolve</span>, <span class="hljs-variable language_">this</span>.<span class="hljs-property">reject</span>)
    &#125;

    <span class="hljs-title function_">initBind</span>(<span class="hljs-params"></span>) &#123;
        <span class="hljs-comment">// 初始化this</span>
        <span class="hljs-variable language_">this</span>.<span class="hljs-property">resolve</span> = <span class="hljs-variable language_">this</span>.<span class="hljs-property">resolve</span>.<span class="hljs-title function_">bind</span>(<span class="hljs-variable language_">this</span>)
        <span class="hljs-variable language_">this</span>.<span class="hljs-property">reject</span> = <span class="hljs-variable language_">this</span>.<span class="hljs-property">reject</span>.<span class="hljs-title function_">bind</span>(<span class="hljs-variable language_">this</span>)
    &#125;

    <span class="hljs-title function_">initValue</span>(<span class="hljs-params"></span>) &#123;
        <span class="hljs-comment">// 初始化值</span>
        <span class="hljs-variable language_">this</span>.<span class="hljs-property">PromiseResult</span> = <span class="hljs-literal">null</span> <span class="hljs-comment">// 终值</span>
        <span class="hljs-variable language_">this</span>.<span class="hljs-property">PromiseState</span> = <span class="hljs-string">&#x27;pending&#x27;</span> <span class="hljs-comment">// 状态</span>
    &#125;

    <span class="hljs-title function_">resolve</span>(<span class="hljs-params">value</span>) &#123;
        <span class="hljs-comment">// 如果执行resolve，状态变为fulfilled</span>
        <span class="hljs-variable language_">this</span>.<span class="hljs-property">PromiseState</span> = <span class="hljs-string">&#x27;fulfilled&#x27;</span>
        <span class="hljs-comment">// 终值为传进来的值</span>
        <span class="hljs-variable language_">this</span>.<span class="hljs-property">PromiseResult</span> = value
    &#125;

    <span class="hljs-title function_">reject</span>(<span class="hljs-params">reason</span>) &#123;
        <span class="hljs-comment">// 如果执行reject，状态变为rejected</span>
        <span class="hljs-variable language_">this</span>.<span class="hljs-property">PromiseState</span> = <span class="hljs-string">&#x27;rejected&#x27;</span>
        <span class="hljs-comment">// 终值为传进来的reason</span>
        <span class="hljs-variable language_">this</span>.<span class="hljs-property">PromiseResult</span> = reason
    &#125;
&#125;</code></pre></div>

<p>咱们来测试一下代码吧：</p>
<div class="code-wrapper"><pre><code class="hljs javascript"><span class="hljs-keyword">const</span> test1 = <span class="hljs-keyword">new</span> <span class="hljs-title class_">MyPromise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> &#123;
    <span class="hljs-title function_">resolve</span>(<span class="hljs-string">&#x27;成功&#x27;</span>)
&#125;)
<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(test1) <span class="hljs-comment">// MyPromise &#123; PromiseState: &#x27;fulfilled&#x27;, PromiseResult: &#x27;成功&#x27; &#125;</span>

<span class="hljs-keyword">const</span> test2 = <span class="hljs-keyword">new</span> <span class="hljs-title class_">MyPromise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> &#123;
    <span class="hljs-title function_">reject</span>(<span class="hljs-string">&#x27;失败&#x27;</span>)
&#125;)
<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(test2) <span class="hljs-comment">// MyPromise &#123; PromiseState: &#x27;rejected&#x27;, PromiseResult: &#x27;失败&#x27; &#125;</span></code></pre></div>

<h3 id="2-状态不可变"><a href="#2-状态不可变" class="headerlink" title="2. 状态不可变"></a>2. 状态不可变</h3><p>其实上面的代码是有问题的，什么问题呢？看看：</p>
<div class="code-wrapper"><pre><code class="hljs javascript"><span class="hljs-keyword">const</span> test1 = <span class="hljs-keyword">new</span> <span class="hljs-title class_">MyPromise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> &#123;
    <span class="hljs-title function_">resolve</span>(<span class="hljs-string">&#x27;成功&#x27;</span>)
    <span class="hljs-title function_">reject</span>(<span class="hljs-string">&#x27;失败&#x27;</span>)
&#125;)
<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(test1) <span class="hljs-comment">// MyPromise &#123; PromiseState: &#x27;rejected&#x27;, PromiseResult: &#x27;失败&#x27; &#125;</span></code></pre></div>

<p>正确的应该是状态为<code>fulfilled</code>，结果是<code>成功</code>，这里明显没有<code>以第一次为准</code></p>
<p>之前说了，Promise只以<code>第一次为准</code>，第一次成功就<code>永久</code>为<code>fulfilled</code>，第一次失败就永远状态为<code>rejected</code>，具体是什么流程呢？我给大家画了一张图：</p>
<p>Promise有三种状态：</p>
<ul>
<li><code>pending</code>：等待中，是初始状态</li>
<li><code>fulfilled</code>：成功状态</li>
<li><code>rejected</code>：失败状态</li>
</ul>
<p>一旦状态从<code>pending</code>变为<code>fulfilled或者rejected</code>，那么此Promise实例的状态就定死了。 <img src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2c9636d819ef4bc78af95fb80c9a7be4~tplv-k3u1fbpfcp-zoom-in-crop-mark:4536:0:0:0.awebp" srcset="/blog/img/loading.gif" lazyload alt="截屏2021-08-01 下午12.33.10.png"></p>
<p>其实实现起来也很容易，加个判断条件就行：</p>
<div class="code-wrapper"><pre><code class="hljs javascript">    <span class="hljs-title function_">resolve</span>(<span class="hljs-params">value</span>) &#123;
        <span class="hljs-comment">// state是不可变的</span>
+        <span class="hljs-keyword">if</span> (<span class="hljs-variable language_">this</span>.<span class="hljs-property">PromiseState</span> !== <span class="hljs-string">&#x27;pending&#x27;</span>) <span class="hljs-keyword">return</span>
        <span class="hljs-comment">// 如果执行resolve，状态变为fulfilled</span>
        <span class="hljs-variable language_">this</span>.<span class="hljs-property">PromiseState</span> = <span class="hljs-string">&#x27;fulfilled&#x27;</span>
        <span class="hljs-comment">// 终值为传进来的值</span>
        <span class="hljs-variable language_">this</span>.<span class="hljs-property">PromiseResult</span> = value
    &#125;

    <span class="hljs-title function_">reject</span>(<span class="hljs-params">reason</span>) &#123;
        <span class="hljs-comment">// state是不可变的</span>
+        <span class="hljs-keyword">if</span> (<span class="hljs-variable language_">this</span>.<span class="hljs-property">PromiseState</span> !== <span class="hljs-string">&#x27;pending&#x27;</span>) <span class="hljs-keyword">return</span>
        <span class="hljs-comment">// 如果执行reject，状态变为rejected</span>
        <span class="hljs-variable language_">this</span>.<span class="hljs-property">PromiseState</span> = <span class="hljs-string">&#x27;rejected&#x27;</span>
        <span class="hljs-comment">// 终值为传进来的reason</span>
        <span class="hljs-variable language_">this</span>.<span class="hljs-property">PromiseResult</span> = reason
    &#125;</code></pre></div>

<p>再来看看效果：</p>
<div class="code-wrapper"><pre><code class="hljs javascript"><span class="hljs-keyword">const</span> test1 = <span class="hljs-keyword">new</span> <span class="hljs-title class_">MyPromise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> &#123;
    <span class="hljs-comment">// 只以第一次为准</span>
    <span class="hljs-title function_">resolve</span>(<span class="hljs-string">&#x27;成功&#x27;</span>)
    <span class="hljs-title function_">reject</span>(<span class="hljs-string">&#x27;失败&#x27;</span>)
&#125;)
<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(test1) <span class="hljs-comment">// MyPromise &#123; PromiseState: &#x27;fulfilled&#x27;, PromiseResult: &#x27;成功&#x27; &#125;</span></code></pre></div>

<h3 id="3-throw"><a href="#3-throw" class="headerlink" title="3. throw"></a>3. throw</h3><p><img src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/fa2e17b24a124dadba540e86350f1302~tplv-k3u1fbpfcp-zoom-in-crop-mark:4536:0:0:0.awebp" srcset="/blog/img/loading.gif" lazyload alt="截屏2021-08-01 下午12.57.17.png"></p>
<p>Promise中有<code>throw</code>的话，就相当于执行了<code>reject</code>。这就要使用<code>try catch</code>了</p>
<div class="code-wrapper"><pre><code class="hljs javascript">+        <span class="hljs-keyword">try</span> &#123;
            <span class="hljs-comment">// 执行传进来的函数</span>
            <span class="hljs-title function_">executor</span>(<span class="hljs-variable language_">this</span>.<span class="hljs-property">resolve</span>, <span class="hljs-variable language_">this</span>.<span class="hljs-property">reject</span>)
+        &#125; <span class="hljs-keyword">catch</span> (e) &#123;
            <span class="hljs-comment">// 捕捉到错误直接执行reject</span>
+            <span class="hljs-variable language_">this</span>.<span class="hljs-title function_">reject</span>(e)
+        &#125;</code></pre></div>

<p>咱们来看看效果：</p>
<div class="code-wrapper"><pre><code class="hljs javascript"><span class="hljs-keyword">const</span> test3 = <span class="hljs-keyword">new</span> <span class="hljs-title class_">MyPromise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> &#123;
    <span class="hljs-keyword">throw</span>(<span class="hljs-string">&#x27;失败&#x27;</span>)
&#125;)
<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(test3) <span class="hljs-comment">// MyPromise &#123; PromiseState: &#x27;rejected&#x27;, PromiseResult: &#x27;失败&#x27; &#125;</span></code></pre></div>

<h2 id="then"><a href="#then" class="headerlink" title="then"></a>then</h2><p>咱们平时使用then方法是这么用的：</p>
<div class="code-wrapper"><pre><code class="hljs javascript"><span class="hljs-comment">// 马上输出 ”成功“</span>
<span class="hljs-keyword">const</span> p1 = <span class="hljs-keyword">new</span> <span class="hljs-title class_">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> &#123;
    <span class="hljs-title function_">resolve</span>(<span class="hljs-string">&#x27;成功&#x27;</span>)
&#125;).<span class="hljs-title function_">then</span>(<span class="hljs-function"><span class="hljs-params">res</span> =&gt;</span> <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(res), <span class="hljs-function"><span class="hljs-params">err</span> =&gt;</span> <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(err))

<span class="hljs-comment">// 1秒后输出 ”失败“</span>
<span class="hljs-keyword">const</span> p2 = <span class="hljs-keyword">new</span> <span class="hljs-title class_">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> &#123;
    <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> &#123;
        <span class="hljs-title function_">reject</span>(<span class="hljs-string">&#x27;失败&#x27;</span>)
    &#125;, <span class="hljs-number">1000</span>)
&#125;).<span class="hljs-title function_">then</span>(<span class="hljs-function"><span class="hljs-params">res</span> =&gt;</span> <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(res), <span class="hljs-function"><span class="hljs-params">err</span> =&gt;</span> <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(err))

<span class="hljs-comment">// 链式调用 输出 200</span>
<span class="hljs-keyword">const</span> p3 = <span class="hljs-keyword">new</span> <span class="hljs-title class_">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> &#123;
    <span class="hljs-title function_">resolve</span>(<span class="hljs-number">100</span>)
&#125;).<span class="hljs-title function_">then</span>(<span class="hljs-function"><span class="hljs-params">res</span> =&gt;</span> <span class="hljs-number">2</span> * res, <span class="hljs-function"><span class="hljs-params">err</span> =&gt;</span> <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(err))
  .<span class="hljs-title function_">then</span>(<span class="hljs-function"><span class="hljs-params">res</span> =&gt;</span> <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(res), <span class="hljs-function"><span class="hljs-params">err</span> =&gt;</span> <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(err))</code></pre></div>

<p>可以总结出这几个知识点：</p>
<ul>
<li>then接收两个回调，一个是<code>成功回调</code>，一个是<code>失败回调</code></li>
<li>当Promise状态为<code>fulfilled</code>执行<code>成功回调</code>，为<code>rejected</code>执行<code>失败回调</code></li>
<li>如resolve或reject在定时器里，<code>则定时器结束后再执行then</code></li>
<li>then支持<code>链式调用</code>，下一次then执行<code>受上一次then返回值的影响</code></li>
</ul>
<p>下面咱们就一步一步地去实现他吧</p>
<h3 id="1-实现then"><a href="#1-实现then" class="headerlink" title="1. 实现then"></a>1. 实现then</h3><div class="code-wrapper"><pre><code class="hljs javascript"><span class="hljs-title function_">then</span>(<span class="hljs-params">onFulfilled, onRejected</span>) &#123;
    <span class="hljs-comment">// 接收两个回调 onFulfilled, onRejected</span>
    
    <span class="hljs-comment">// 参数校验，确保一定是函数</span>
    onFulfilled = <span class="hljs-keyword">typeof</span> onFulfilled === <span class="hljs-string">&#x27;function&#x27;</span> ? onFulfilled : <span class="hljs-function"><span class="hljs-params">val</span> =&gt;</span> val
    onRejected = <span class="hljs-keyword">typeof</span> onRejected === <span class="hljs-string">&#x27;function&#x27;</span> ? onRejected : <span class="hljs-function"><span class="hljs-params">reason</span> =&gt;</span> &#123; <span class="hljs-keyword">throw</span> reason &#125;

    <span class="hljs-keyword">if</span> (<span class="hljs-variable language_">this</span>.<span class="hljs-property">PromiseState</span> === <span class="hljs-string">&#x27;fulfilled&#x27;</span>) &#123;
        <span class="hljs-comment">// 如果当前为成功状态，执行第一个回调</span>
        <span class="hljs-title function_">onFulfilled</span>(<span class="hljs-variable language_">this</span>.<span class="hljs-property">PromiseResult</span>)
    &#125; <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (<span class="hljs-variable language_">this</span>.<span class="hljs-property">PromiseState</span> === <span class="hljs-string">&#x27;rejected&#x27;</span>) &#123;
        <span class="hljs-comment">// 如果当前为失败状态，执行第二哥回调</span>
        <span class="hljs-title function_">onRejected</span>(<span class="hljs-variable language_">this</span>.<span class="hljs-property">PromiseResult</span>)
    &#125;
&#125;</code></pre></div>

<p>咱们来看看效果：</p>
<div class="code-wrapper"><pre><code class="hljs javascript"><span class="hljs-comment">// 输出 ”成功“</span>
<span class="hljs-keyword">const</span> test = <span class="hljs-keyword">new</span> <span class="hljs-title class_">MyPromise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> &#123;
    <span class="hljs-title function_">resolve</span>(<span class="hljs-string">&#x27;成功&#x27;</span>)
&#125;).<span class="hljs-title function_">then</span>(<span class="hljs-function"><span class="hljs-params">res</span> =&gt;</span> <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(res), <span class="hljs-function"><span class="hljs-params">err</span> =&gt;</span> <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(err))</code></pre></div>

<h3 id="2-定时器情况"><a href="#2-定时器情况" class="headerlink" title="2. 定时器情况"></a>2. 定时器情况</h3><p>上面我们已经实现了<code>then</code>的基本功能。那如果是<code>定时器</code>情况呢？</p>
<p>还是那个代码，怎么才能保证，1秒后才执行then里的失败回调呢？</p>
<div class="code-wrapper"><pre><code class="hljs javascript"><span class="hljs-comment">// 1秒后输出 ”成功“</span>
<span class="hljs-keyword">const</span> p2 = <span class="hljs-keyword">new</span> <span class="hljs-title class_">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> &#123;
    <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> &#123;
        <span class="hljs-title function_">reject</span>(<span class="hljs-string">&#x27;失败&#x27;</span>)
    &#125;, <span class="hljs-number">1000</span>)
&#125;).<span class="hljs-title function_">then</span>(<span class="hljs-function"><span class="hljs-params">res</span> =&gt;</span> <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(res), <span class="hljs-function"><span class="hljs-params">err</span> =&gt;</span> <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(err))</code></pre></div>

<p>我们不能确保1秒后才执行then函数，但是我们可以保证1秒后再执行then里的回调，可能这里大家有点懵逼，我同样用一张图给大家讲讲吧：</p>
<p><img src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/6ba5a2544b1144548cdc63362fa27d23~tplv-k3u1fbpfcp-zoom-in-crop-mark:4536:0:0:0.awebp" srcset="/blog/img/loading.gif" lazyload alt="截屏2021-08-01 下午9.05.24.png"></p>
<p>也就是在这1秒时间内，我们可以先把then里的两个回调保存起来，然后等到1秒过后，执行了resolve或者reject，咱们再去判断状态，并且判断要去执行刚刚保存的两个回调中的哪一个回调。</p>
<p>那么问题来了，我们怎么知道当前1秒还没走完甚至还没开始走呢？其实很好判断，只要状态是<code>pending</code>，那就证明定时器还没跑完，因为如果定时器跑完的话，那状态肯定就不是<code>pending</code>，而是<code>fulfilled或者rejected</code></p>
<p>那是用什么来保存这些回调呢？建议使用<code>数组</code>，因为一个promise实例可能会<code>多次then</code>，用数组就一个一个保存了</p>
<div class="code-wrapper"><pre><code class="hljs javascript">    <span class="hljs-title function_">initValue</span>(<span class="hljs-params"></span>) &#123;
        <span class="hljs-comment">// 初始化值</span>
        <span class="hljs-variable language_">this</span>.<span class="hljs-property">PromiseResult</span> = <span class="hljs-literal">null</span> <span class="hljs-comment">// 终值</span>
        <span class="hljs-variable language_">this</span>.<span class="hljs-property">PromiseState</span> = <span class="hljs-string">&#x27;pending&#x27;</span> <span class="hljs-comment">// 状态</span>
+        <span class="hljs-variable language_">this</span>.<span class="hljs-property">onFulfilledCallbacks</span> = [] <span class="hljs-comment">// 保存成功回调</span>
+        <span class="hljs-variable language_">this</span>.<span class="hljs-property">onRejectedCallbacks</span> = [] <span class="hljs-comment">// 保存失败回调</span>
    &#125;

    <span class="hljs-title function_">resolve</span>(<span class="hljs-params">value</span>) &#123;
        <span class="hljs-comment">// state是不可变的</span>
        <span class="hljs-keyword">if</span> (<span class="hljs-variable language_">this</span>.<span class="hljs-property">PromiseState</span> !== <span class="hljs-string">&#x27;pending&#x27;</span>) <span class="hljs-keyword">return</span>
        <span class="hljs-comment">// 如果执行resolve，状态变为fulfilled</span>
        <span class="hljs-variable language_">this</span>.<span class="hljs-property">PromiseState</span> = <span class="hljs-string">&#x27;fulfilled&#x27;</span>
        <span class="hljs-comment">// 终值为传进来的值</span>
        <span class="hljs-variable language_">this</span>.<span class="hljs-property">PromiseResult</span> = value
        <span class="hljs-comment">// 执行保存的成功回调</span>
+        <span class="hljs-keyword">while</span> (<span class="hljs-variable language_">this</span>.<span class="hljs-property">onFulfilledCallbacks</span>.<span class="hljs-property">length</span>) &#123;
+            <span class="hljs-variable language_">this</span>.<span class="hljs-property">onFulfilledCallbacks</span>.<span class="hljs-title function_">shift</span>()(<span class="hljs-variable language_">this</span>.<span class="hljs-property">PromiseResult</span>)
+        &#125;
    &#125;

    <span class="hljs-title function_">reject</span>(<span class="hljs-params">reason</span>) &#123;
        <span class="hljs-comment">// state是不可变的</span>
        <span class="hljs-keyword">if</span> (<span class="hljs-variable language_">this</span>.<span class="hljs-property">PromiseState</span> !== <span class="hljs-string">&#x27;pending&#x27;</span>) <span class="hljs-keyword">return</span>
        <span class="hljs-comment">// 如果执行reject，状态变为rejected</span>
        <span class="hljs-variable language_">this</span>.<span class="hljs-property">PromiseState</span> = <span class="hljs-string">&#x27;rejected&#x27;</span>
        <span class="hljs-comment">// 终值为传进来的reason</span>
        <span class="hljs-variable language_">this</span>.<span class="hljs-property">PromiseResult</span> = reason
        <span class="hljs-comment">// 执行保存的失败回调</span>
+        <span class="hljs-keyword">while</span> (<span class="hljs-variable language_">this</span>.<span class="hljs-property">onRejectedCallbacks</span>.<span class="hljs-property">length</span>) &#123;
+            <span class="hljs-variable language_">this</span>.<span class="hljs-property">onRejectedCallbacks</span>.<span class="hljs-title function_">shift</span>()(<span class="hljs-variable language_">this</span>.<span class="hljs-property">PromiseResult</span>)
+        &#125;
    &#125;
    
    <span class="hljs-title function_">then</span>(<span class="hljs-params">onFulfilled, onRejected</span>) &#123;
        <span class="hljs-comment">// 接收两个回调 onFulfilled, onRejected</span>

        <span class="hljs-comment">// 参数校验，确保一定是函数</span>
        onFulfilled = <span class="hljs-keyword">typeof</span> onFulfilled === <span class="hljs-string">&#x27;function&#x27;</span> ? onFulfilled : <span class="hljs-function"><span class="hljs-params">val</span> =&gt;</span> val
        onRejected = <span class="hljs-keyword">typeof</span> onRejected === <span class="hljs-string">&#x27;function&#x27;</span> ? onRejected : <span class="hljs-function"><span class="hljs-params">reason</span> =&gt;</span> &#123; <span class="hljs-keyword">throw</span> reason &#125;

        <span class="hljs-keyword">if</span> (<span class="hljs-variable language_">this</span>.<span class="hljs-property">PromiseState</span> === <span class="hljs-string">&#x27;fulfilled&#x27;</span>) &#123;
            <span class="hljs-comment">// 如果当前为成功状态，执行第一个回调</span>
            <span class="hljs-title function_">onFulfilled</span>(<span class="hljs-variable language_">this</span>.<span class="hljs-property">PromiseResult</span>)
        &#125; <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (<span class="hljs-variable language_">this</span>.<span class="hljs-property">PromiseState</span> === <span class="hljs-string">&#x27;rejected&#x27;</span>) &#123;
            <span class="hljs-comment">// 如果当前为失败状态，执行第二哥回调</span>
            <span class="hljs-title function_">onRejected</span>(<span class="hljs-variable language_">this</span>.<span class="hljs-property">PromiseResult</span>)
+        &#125; <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (<span class="hljs-variable language_">this</span>.<span class="hljs-property">PromiseState</span> === <span class="hljs-string">&#x27;pending&#x27;</span>) &#123;
+            <span class="hljs-comment">// 如果状态为待定状态，暂时保存两个回调</span>
+            <span class="hljs-variable language_">this</span>.<span class="hljs-property">onFulfilledCallbacks</span>.<span class="hljs-title function_">push</span>(onFulfilled.<span class="hljs-title function_">bind</span>(<span class="hljs-variable language_">this</span>))
+            <span class="hljs-variable language_">this</span>.<span class="hljs-property">onRejectedCallbacks</span>.<span class="hljs-title function_">push</span>(onRejected.<span class="hljs-title function_">bind</span>(<span class="hljs-variable language_">this</span>))
+        &#125;

    &#125;</code></pre></div>

<p>加完上面的代码，咱们来看看定时器的效果吧：</p>
<div class="code-wrapper"><pre><code class="hljs javascript"><span class="hljs-keyword">const</span> test2 = <span class="hljs-keyword">new</span> <span class="hljs-title class_">MyPromise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> &#123;
    <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> &#123;
        <span class="hljs-title function_">resolve</span>(<span class="hljs-string">&#x27;成功&#x27;</span>) <span class="hljs-comment">// 1秒后输出 成功</span>
        <span class="hljs-comment">// resolve(&#x27;成功&#x27;) // 1秒后输出 失败</span>
    &#125;, <span class="hljs-number">1000</span>)
&#125;).<span class="hljs-title function_">then</span>(<span class="hljs-function"><span class="hljs-params">res</span> =&gt;</span> <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(res), <span class="hljs-function"><span class="hljs-params">err</span> =&gt;</span> <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(err))</code></pre></div>

<h3 id="3-链式调用"><a href="#3-链式调用" class="headerlink" title="3. 链式调用"></a>3. 链式调用</h3><p>then支持<code>链式调用</code>，下一次then执行<code>受上一次then返回值的影响</code>，给大家举个例子：</p>
<div class="code-wrapper"><pre><code class="hljs javascript"><span class="hljs-comment">// 链式调用 输出 200</span>
<span class="hljs-keyword">const</span> p3 = <span class="hljs-keyword">new</span> <span class="hljs-title class_">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> &#123;
    <span class="hljs-title function_">resolve</span>(<span class="hljs-number">100</span>)
&#125;).<span class="hljs-title function_">then</span>(<span class="hljs-function"><span class="hljs-params">res</span> =&gt;</span> <span class="hljs-number">2</span> * res, <span class="hljs-function"><span class="hljs-params">err</span> =&gt;</span> <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(err))
    .<span class="hljs-title function_">then</span>(<span class="hljs-function"><span class="hljs-params">res</span> =&gt;</span> <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(res), <span class="hljs-function"><span class="hljs-params">err</span> =&gt;</span> <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(err))

<span class="hljs-comment">// 链式调用 输出300</span>
<span class="hljs-keyword">const</span> p4 = <span class="hljs-keyword">new</span> <span class="hljs-title class_">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> &#123;
    <span class="hljs-title function_">resolve</span>(<span class="hljs-number">100</span>)
&#125;).<span class="hljs-title function_">then</span>(<span class="hljs-function"><span class="hljs-params">res</span> =&gt;</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> <span class="hljs-title function_">resolve</span>(<span class="hljs-number">3</span> * res)), <span class="hljs-function"><span class="hljs-params">err</span> =&gt;</span> <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(err))
    .<span class="hljs-title function_">then</span>(<span class="hljs-function"><span class="hljs-params">res</span> =&gt;</span> <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(res), <span class="hljs-function"><span class="hljs-params">err</span> =&gt;</span> <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(err))</code></pre></div>

<p><strong>从上方例子，我们可以获取到几个知识点：</strong></p>
<ul>
<li>1、then方法本身会返回一个新的Promise对象</li>
<li>2、如果返回值是promise对象，返回值为成功，新promise就是成功</li>
<li>3、如果返回值是promise对象，返回值为失败，新promise就是失败</li>
<li>4、如果返回值非promise对象，新promise对象就是成功，值为此返回值</li>
</ul>
<p>咱们知道then是Promise上的方法，那如何实现then完还能再then呢？很简单，then执行后返回一个<code>Promise对象</code>就行了，就能保证then完还能继续执行then：</p>
<p><img src="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/62a3c3afcf0a4262a1a7e52231c34dbc~tplv-k3u1fbpfcp-zoom-in-crop-mark:4536:0:0:0.awebp" srcset="/blog/img/loading.gif" lazyload alt="截屏2021-08-01 下午9.06.02.png"></p>
<p>代码实现：</p>
<div class="code-wrapper"><pre><code class="hljs javascript"><span class="hljs-title function_">then</span>(<span class="hljs-params">onFulfilled, onRejected</span>) &#123;
    <span class="hljs-comment">// 接收两个回调 onFulfilled, onRejected</span>

    <span class="hljs-comment">// 参数校验，确保一定是函数</span>
    onFulfilled = <span class="hljs-keyword">typeof</span> onFulfilled === <span class="hljs-string">&#x27;function&#x27;</span> ? onFulfilled : <span class="hljs-function"><span class="hljs-params">val</span> =&gt;</span> val
    onRejected = <span class="hljs-keyword">typeof</span> onRejected === <span class="hljs-string">&#x27;function&#x27;</span> ? onRejected : <span class="hljs-function"><span class="hljs-params">reason</span> =&gt;</span> &#123; <span class="hljs-keyword">throw</span> reason &#125;


    <span class="hljs-keyword">var</span> thenPromise = <span class="hljs-keyword">new</span> <span class="hljs-title class_">MyPromise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> &#123;

        <span class="hljs-keyword">const</span> <span class="hljs-title function_">resolvePromise</span> = cb =&gt; &#123;
            <span class="hljs-keyword">try</span> &#123;
                <span class="hljs-keyword">const</span> x = <span class="hljs-title function_">cb</span>(<span class="hljs-variable language_">this</span>.<span class="hljs-property">PromiseResult</span>)
                <span class="hljs-keyword">if</span> (x === thenPromise) &#123;
                    <span class="hljs-comment">// 不能返回自身哦</span>
                    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Error</span>(<span class="hljs-string">&#x27;不能返回自身。。。&#x27;</span>)
                &#125;
                <span class="hljs-keyword">if</span> (x <span class="hljs-keyword">instanceof</span> <span class="hljs-title class_">MyPromise</span>) &#123;
                    <span class="hljs-comment">// 如果返回值是Promise</span>
                    <span class="hljs-comment">// 如果返回值是promise对象，返回值为成功，新promise就是成功</span>
                    <span class="hljs-comment">// 如果返回值是promise对象，返回值为失败，新promise就是失败</span>
                    <span class="hljs-comment">// 谁知道返回的promise是失败成功？只有then知道</span>
                    x.<span class="hljs-title function_">then</span>(resolve, reject)
                &#125; <span class="hljs-keyword">else</span> &#123;
                    <span class="hljs-comment">// 非Promise就直接成功</span>
                    <span class="hljs-title function_">resolve</span>(x)
                &#125;
            &#125; <span class="hljs-keyword">catch</span> (err) &#123;
                <span class="hljs-comment">// 处理报错</span>
                <span class="hljs-title function_">reject</span>(err)
                <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Error</span>(err)
            &#125;
        &#125;

        <span class="hljs-keyword">if</span> (<span class="hljs-variable language_">this</span>.<span class="hljs-property">PromiseState</span> === <span class="hljs-string">&#x27;fulfilled&#x27;</span>) &#123;
            <span class="hljs-comment">// 如果当前为成功状态，执行第一个回调</span>
            <span class="hljs-title function_">resolvePromise</span>(onFulfilled)
        &#125; <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (<span class="hljs-variable language_">this</span>.<span class="hljs-property">PromiseState</span> === <span class="hljs-string">&#x27;rejected&#x27;</span>) &#123;
            <span class="hljs-comment">// 如果当前为失败状态，执行第二个回调</span>
            <span class="hljs-title function_">resolvePromise</span>(onRejected)
        &#125; <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (<span class="hljs-variable language_">this</span>.<span class="hljs-property">PromiseState</span> === <span class="hljs-string">&#x27;pending&#x27;</span>) &#123;
            <span class="hljs-comment">// 如果状态为待定状态，暂时保存两个回调</span>
            <span class="hljs-comment">// 如果状态为待定状态，暂时保存两个回调</span>
            <span class="hljs-variable language_">this</span>.<span class="hljs-property">onFulfilledCallbacks</span>.<span class="hljs-title function_">push</span>(resolvePromise.<span class="hljs-title function_">bind</span>(<span class="hljs-variable language_">this</span>, onFulfilled))
            <span class="hljs-variable language_">this</span>.<span class="hljs-property">onRejectedCallbacks</span>.<span class="hljs-title function_">push</span>(resolvePromise.<span class="hljs-title function_">bind</span>(<span class="hljs-variable language_">this</span>, onRejected))
        &#125;
    &#125;)

    <span class="hljs-comment">// 返回这个包装的Promise</span>
    <span class="hljs-keyword">return</span> thenPromise

&#125;</code></pre></div>

<p>现在大家可以试试效果怎么样了，大家要<strong>边敲边试</strong>哦：</p>
<div class="code-wrapper"><pre><code class="hljs javascript"><span class="hljs-keyword">const</span> test3 = <span class="hljs-keyword">new</span> <span class="hljs-title class_">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> &#123;
  <span class="hljs-title function_">resolve</span>(<span class="hljs-number">100</span>) <span class="hljs-comment">// 输出 状态：成功 值： 200</span>
  <span class="hljs-comment">// reject(100) // 输出 状态：成功 值：300</span>
&#125;).<span class="hljs-title function_">then</span>(<span class="hljs-function"><span class="hljs-params">res</span> =&gt;</span> <span class="hljs-number">2</span> * res, <span class="hljs-function"><span class="hljs-params">err</span> =&gt;</span> <span class="hljs-number">3</span> * err)
  .<span class="hljs-title function_">then</span>(<span class="hljs-function"><span class="hljs-params">res</span> =&gt;</span> <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&#x27;成功&#x27;</span>, res), <span class="hljs-function"><span class="hljs-params">err</span> =&gt;</span> <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&#x27;失败&#x27;</span>, err))


  <span class="hljs-keyword">const</span> test4 = <span class="hljs-keyword">new</span> <span class="hljs-title class_">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> &#123;
    <span class="hljs-title function_">resolve</span>(<span class="hljs-number">100</span>) <span class="hljs-comment">// 输出 状态：失败 值：200</span>
    <span class="hljs-comment">// reject(100) // 输出 状态：成功 值：300</span>
    <span class="hljs-comment">// 这里可没搞反哦。真的搞懂了，就知道了为啥这里是反的</span>
  &#125;).<span class="hljs-title function_">then</span>(<span class="hljs-function"><span class="hljs-params">res</span> =&gt;</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> <span class="hljs-title function_">reject</span>(<span class="hljs-number">2</span> * res)), <span class="hljs-function"><span class="hljs-params">err</span> =&gt;</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> <span class="hljs-title function_">resolve</span>(<span class="hljs-number">3</span> * err)))
    .<span class="hljs-title function_">then</span>(<span class="hljs-function"><span class="hljs-params">res</span> =&gt;</span> <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&#x27;成功&#x27;</span>, res), <span class="hljs-function"><span class="hljs-params">err</span> =&gt;</span> <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&#x27;失败&#x27;</span>, err))</code></pre></div>

<h3 id="4-微任务"><a href="#4-微任务" class="headerlink" title="4. 微任务"></a>4. 微任务</h3><p>看过<code>js执行机制</code>的兄弟都知道，then方法是<code>微任务</code>，啥叫微任务呢？其实不知道也不要紧，我通过下面例子让你知道：</p>
<div class="code-wrapper"><pre><code class="hljs javascript"><span class="hljs-keyword">const</span> p = <span class="hljs-keyword">new</span> <span class="hljs-title class_">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> &#123;
    <span class="hljs-title function_">resolve</span>(<span class="hljs-number">1</span>)
&#125;).<span class="hljs-title function_">then</span>(<span class="hljs-function"><span class="hljs-params">res</span> =&gt;</span> <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(res), <span class="hljs-function"><span class="hljs-params">err</span> =&gt;</span> <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(err))

<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-number">2</span>)

输出顺序是 <span class="hljs-number">2</span> <span class="hljs-number">1</span></code></pre></div>

<p>为啥不是 1 2 呢？因为then是个微任务啊。。。同样，我们也要给我们的MyPromise加上这个特性(我这里使用定时器，大家别介意哈)</p>
<p>只需要让<code>resolvePromise函数</code>异步执行就可以了</p>
<div class="code-wrapper"><pre><code class="hljs javascript"> <span class="hljs-keyword">const</span> <span class="hljs-title function_">resolvePromise</span> = cb =&gt; &#123;
    <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> &#123;
        <span class="hljs-keyword">try</span> &#123;
            <span class="hljs-keyword">const</span> x = <span class="hljs-title function_">cb</span>(<span class="hljs-variable language_">this</span>.<span class="hljs-property">PromiseResult</span>)
            <span class="hljs-keyword">if</span> (x === thenPromise) &#123;
                <span class="hljs-comment">// 不能返回自身哦</span>
                <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Error</span>(<span class="hljs-string">&#x27;不能返回自身。。。&#x27;</span>)
            &#125;
            <span class="hljs-keyword">if</span> (x <span class="hljs-keyword">instanceof</span> <span class="hljs-title class_">MyPromise</span>) &#123;
                <span class="hljs-comment">// 如果返回值是Promise</span>
                <span class="hljs-comment">// 如果返回值是promise对象，返回值为成功，新promise就是成功</span>
                <span class="hljs-comment">// 如果返回值是promise对象，返回值为失败，新promise就是失败</span>
                <span class="hljs-comment">// 谁知道返回的promise是失败成功？只有then知道</span>
                x.<span class="hljs-title function_">then</span>(resolve, reject)
            &#125; <span class="hljs-keyword">else</span> &#123;
                <span class="hljs-comment">// 非Promise就直接成功</span>
                <span class="hljs-title function_">resolve</span>(x)
            &#125;
        &#125; <span class="hljs-keyword">catch</span> (err) &#123;
            <span class="hljs-comment">// 处理报错</span>
            <span class="hljs-title function_">reject</span>(err)
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Error</span>(err)
        &#125;
    &#125;)
&#125;</code></pre></div>

<p>看看效果：</p>
<div class="code-wrapper"><pre><code class="hljs javascript"><span class="hljs-keyword">const</span> test4 = <span class="hljs-keyword">new</span> <span class="hljs-title class_">MyPromise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> &#123;
    <span class="hljs-title function_">resolve</span>(<span class="hljs-number">1</span>)
&#125;).<span class="hljs-title function_">then</span>(<span class="hljs-function"><span class="hljs-params">res</span> =&gt;</span> <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(res), <span class="hljs-function"><span class="hljs-params">err</span> =&gt;</span> <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(err))

<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-number">2</span>)

输出顺序 <span class="hljs-number">2</span> <span class="hljs-number">1</span>
</code></pre></div>

<h2 id="其他方法"><a href="#其他方法" class="headerlink" title="其他方法"></a>其他方法</h2><p>这些方法都比较简单，我就不太过详细地讲了，大家也可以借这个机会，自己摸索，巩固这篇文章的知识。</p>
<h3 id="all"><a href="#all" class="headerlink" title="all"></a>all</h3><ul>
<li>接收一个Promise数组，数组中如有非Promise项，则此项当做成功</li>
<li>如果所有Promise都成功，则返回成功结果数组</li>
<li>如果有一个Promise失败，则返回这个失败结果</li>
</ul>
<div class="code-wrapper"><pre><code class="hljs javascript"><span class="hljs-keyword">static</span> <span class="hljs-title function_">all</span>(<span class="hljs-params">promises</span>) &#123;
    <span class="hljs-keyword">const</span> result = []
    <span class="hljs-keyword">let</span> count = <span class="hljs-number">0</span>
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">MyPromise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> &#123;
        <span class="hljs-keyword">const</span> <span class="hljs-title function_">addData</span> = (<span class="hljs-params">index, value</span>) =&gt; &#123;
            result[index] = value
            count++
            <span class="hljs-keyword">if</span> (count === promises.<span class="hljs-property">length</span>) <span class="hljs-title function_">resolve</span>(result)
        &#125;
        promises.<span class="hljs-title function_">forEach</span>(<span class="hljs-function">(<span class="hljs-params">promise, index</span>) =&gt;</span> &#123;
            <span class="hljs-keyword">if</span> (promise <span class="hljs-keyword">instanceof</span> <span class="hljs-title class_">MyPromise</span>) &#123;
                promise.<span class="hljs-title function_">then</span>(<span class="hljs-function"><span class="hljs-params">res</span> =&gt;</span> &#123;
                    <span class="hljs-title function_">addData</span>(index, res)
                &#125;, <span class="hljs-function"><span class="hljs-params">err</span> =&gt;</span> <span class="hljs-title function_">reject</span>(err))
            &#125; <span class="hljs-keyword">else</span> &#123;
                <span class="hljs-title function_">addData</span>(index, promise)
            &#125;
        &#125;)
    &#125;)
&#125;</code></pre></div>

<h3 id="race"><a href="#race" class="headerlink" title="race"></a>race</h3><ul>
<li>接收一个Promise数组，数组中如有非Promise项，则此项当做成功</li>
<li>哪个Promise最快得到结果，就返回那个结果，无论成功失败</li>
</ul>
<div class="code-wrapper"><pre><code class="hljs javascript"><span class="hljs-keyword">static</span> <span class="hljs-title function_">race</span>(<span class="hljs-params">promises</span>) &#123;
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">MyPromise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> &#123;
        promises.<span class="hljs-title function_">forEach</span>(<span class="hljs-function"><span class="hljs-params">promise</span> =&gt;</span> &#123;
            <span class="hljs-keyword">if</span> (promise <span class="hljs-keyword">instanceof</span> <span class="hljs-title class_">MyPromise</span>) &#123;
                promise.<span class="hljs-title function_">then</span>(<span class="hljs-function"><span class="hljs-params">res</span> =&gt;</span> &#123;
                    <span class="hljs-title function_">resolve</span>(res)
                &#125;, <span class="hljs-function"><span class="hljs-params">err</span> =&gt;</span> &#123;
                    <span class="hljs-title function_">reject</span>(err)
                &#125;)
            &#125; <span class="hljs-keyword">else</span> &#123;
                <span class="hljs-title function_">resolve</span>(promise)
            &#125;
        &#125;)
    &#125;)
&#125;</code></pre></div>

<h3 id="allSettled"><a href="#allSettled" class="headerlink" title="allSettled"></a>allSettled</h3><ul>
<li>接收一个Promise数组，数组中如有非Promise项，则此项当做成功</li>
<li>把每一个Promise的结果，集合成数组，返回</li>
</ul>
<div class="code-wrapper"><pre><code class="hljs javascript"><span class="hljs-keyword">static</span> <span class="hljs-title function_">allSettled</span>(<span class="hljs-params">promises</span>) &#123;
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> &#123;
        <span class="hljs-keyword">const</span> res = []
        <span class="hljs-keyword">let</span> count = <span class="hljs-number">0</span>
        <span class="hljs-keyword">const</span> <span class="hljs-title function_">addData</span> = (<span class="hljs-params">status, value, i</span>) =&gt; &#123;
            res[i] = &#123;
                status,
                value
            &#125;
            count++
            <span class="hljs-keyword">if</span> (count === promises.<span class="hljs-property">length</span>) &#123;
                <span class="hljs-title function_">resolve</span>(res)
            &#125;
        &#125;
        promises.<span class="hljs-title function_">forEach</span>(<span class="hljs-function">(<span class="hljs-params">promise, i</span>) =&gt;</span> &#123;
            <span class="hljs-keyword">if</span> (promise <span class="hljs-keyword">instanceof</span> <span class="hljs-title class_">MyPromise</span>) &#123;
                promise.<span class="hljs-title function_">then</span>(<span class="hljs-function"><span class="hljs-params">res</span> =&gt;</span> &#123;
                    <span class="hljs-title function_">addData</span>(<span class="hljs-string">&#x27;fulfilled&#x27;</span>, res, i)
                &#125;, <span class="hljs-function"><span class="hljs-params">err</span> =&gt;</span> &#123;
                    <span class="hljs-title function_">addData</span>(<span class="hljs-string">&#x27;rejected&#x27;</span>, err, i)
                &#125;)
            &#125; <span class="hljs-keyword">else</span> &#123;
                <span class="hljs-title function_">addData</span>(<span class="hljs-string">&#x27;fulfilled&#x27;</span>, promise, i)
            &#125;
        &#125;)
    &#125;)
&#125;</code></pre></div>

<h3 id="any"><a href="#any" class="headerlink" title="any"></a>any</h3><p>any与all相反</p>
<ul>
<li>接收一个Promise数组，数组中如有非Promise项，则此项当做成功</li>
<li>如果有一个Promise成功，则返回这个成功结果</li>
<li>如果所有Promise都失败，则报错</li>
</ul>
<div class="code-wrapper"><pre><code class="hljs javascript">    <span class="hljs-keyword">static</span> <span class="hljs-title function_">any</span>(<span class="hljs-params">promises</span>) &#123;
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> &#123;
            <span class="hljs-keyword">let</span> count = <span class="hljs-number">0</span>
            promises.<span class="hljs-title function_">forEach</span>(<span class="hljs-function">(<span class="hljs-params">promise</span>) =&gt;</span> &#123;
                promise.<span class="hljs-title function_">then</span>(<span class="hljs-function"><span class="hljs-params">val</span> =&gt;</span> &#123;
                    <span class="hljs-title function_">resolve</span>(val)
                &#125;, <span class="hljs-function"><span class="hljs-params">err</span> =&gt;</span> &#123;
                    count++
                    <span class="hljs-keyword">if</span> (count === promises.<span class="hljs-property">length</span>) &#123;
                        <span class="hljs-title function_">reject</span>(<span class="hljs-keyword">new</span> <span class="hljs-title class_">AggregateError</span>(<span class="hljs-string">&#x27;All promises were rejected&#x27;</span>))
                    &#125;
                &#125;)
            &#125;)
        &#125;)
    &#125;
&#125;</code></pre></div>


                
              </div>
            
            <hr/>
            <div>
              <div class="post-metas my-3">
  
    <div class="post-meta mr-3 d-flex align-items-center">
      <i class="iconfont icon-category"></i>
      

<span class="category-chains">
  
  
    
      <span class="category-chain">
        
  <a href="/blog/categories/javascript/" class="category-chain-item">javascript</a>
  
  
    <span>></span>
    
  <a href="/blog/categories/javascript/es6/" class="category-chain-item">es6</a>
  
  

  

      </span>
    
  
</span>

    </div>
  
  
    <div class="post-meta">
      <i class="iconfont icon-tags"></i>
      
        <a href="/blog/tags/promise/">#promise</a>
      
    </div>
  
</div>


              

              
                <div class="post-prevnext my-3">
                  <article class="post-prev col-6">
                    
                    
                      <a href="/blog/interview-react.html" title="面试题汇总之React">
                        <i class="iconfont icon-arrowleft"></i>
                        <span class="hidden-mobile">面试题汇总之React</span>
                        <span class="visible-mobile">上一篇</span>
                      </a>
                    
                  </article>
                  <article class="post-next col-6">
                    
                    
                      <a href="/blog/interview-vue.html" title="面试题汇总之Vue">
                        <span class="hidden-mobile">面试题汇总之Vue</span>
                        <span class="visible-mobile">下一篇</span>
                        <i class="iconfont icon-arrowright"></i>
                      </a>
                    
                  </article>
                </div>
              
            </div>

            
          </article>
        </div>
      </div>
    </div>

    <div class="side-col d-none d-lg-block col-lg-2">
      
  <aside class="sidebar" style="margin-left: -1rem">
    <div id="toc">
  <p class="toc-header"><i class="iconfont icon-list"></i>&nbsp;目录</p>
  <div class="toc-body" id="toc-body"></div>
</div>



  </aside>


    </div>
  </div>
</div>





  



  



  



  



  







    

    
      <a id="scroll-top-button" aria-label="TOP" href="#" role="button">
        <i class="iconfont icon-arrowup" aria-hidden="true"></i>
      </a>
    

    
      <div class="modal fade" id="modalSearch" tabindex="-1" role="dialog" aria-labelledby="ModalLabel"
     aria-hidden="true">
  <div class="modal-dialog modal-dialog-scrollable modal-lg" role="document">
    <div class="modal-content">
      <div class="modal-header text-center">
        <h4 class="modal-title w-100 font-weight-bold">搜索</h4>
        <button type="button" id="local-search-close" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body mx-3">
        <div class="md-form mb-5">
          <input type="text" id="local-search-input" class="form-control validate">
          <label data-error="x" data-success="v" for="local-search-input">关键词</label>
        </div>
        <div class="list-group" id="local-search-result"></div>
      </div>
    </div>
  </div>
</div>

    

    
  </main>

  <footer>
    <div class="footer-inner">
  
    <div class="footer-content">
       <span>枫🍁川</span> <i class="iconfont icon-love"></i> <span>前端小白</span> 
    </div>
  
  
    <div class="statistics">
  
  

  
    
      <span id="busuanzi_container_site_pv" style="display: none">
        总访问量 
        <span id="busuanzi_value_site_pv"></span>
         次
      </span>
    
    
      <span id="busuanzi_container_site_uv" style="display: none">
        总访客数 
        <span id="busuanzi_value_site_uv"></span>
         人
      </span>
    
    
  
</div>

  
  
  
</div>
<script type="text/javascript" src="/blog/js/click-love.js"></script>

  </footer>

  <!-- Scripts -->
  
  <script  src="https://lib.baomitu.com/nprogress/0.2.0/nprogress.min.js" ></script>
  <link  rel="stylesheet" href="https://lib.baomitu.com/nprogress/0.2.0/nprogress.min.css" />

  <script>
    NProgress.configure({"showSpinner":false,"trickleSpeed":100})
    NProgress.start()
    window.addEventListener('load', function() {
      NProgress.done();
    })
  </script>


<script  src="https://lib.baomitu.com/jquery/3.6.0/jquery.min.js" ></script>
<script  src="https://lib.baomitu.com/twitter-bootstrap/4.6.1/js/bootstrap.min.js" ></script>
<script  src="/blog/js/events.js" ></script>
<script  src="/blog/js/plugins.js" ></script>


  <script  src="https://lib.baomitu.com/typed.js/2.0.12/typed.min.js" ></script>
  <script>
    (function (window, document) {
      var typing = Fluid.plugins.typing;
      var subtitle = document.getElementById('subtitle');
      if (!subtitle || !typing) {
        return;
      }
      var text = subtitle.getAttribute('data-typed-text');
      
        typing(text);
      
    })(window, document);
  </script>




  
    <script  src="/blog/js/img-lazyload.js" ></script>
  




  
<script>
  Fluid.utils.createScript('https://lib.baomitu.com/tocbot/4.18.2/tocbot.min.js', function() {
    var toc = jQuery('#toc');
    if (toc.length === 0 || !window.tocbot) { return; }
    var boardCtn = jQuery('#board-ctn');
    var boardTop = boardCtn.offset().top;

    window.tocbot.init({
      tocSelector     : '#toc-body',
      contentSelector : '.markdown-body',
      headingSelector : CONFIG.toc.headingSelector || 'h1,h2,h3,h4,h5,h6',
      linkClass       : 'tocbot-link',
      activeLinkClass : 'tocbot-active-link',
      listClass       : 'tocbot-list',
      isCollapsedClass: 'tocbot-is-collapsed',
      collapsibleClass: 'tocbot-is-collapsible',
      collapseDepth   : CONFIG.toc.collapseDepth || 0,
      scrollSmooth    : true,
      headingsOffset  : -boardTop
    });
    if (toc.find('.toc-list-item').length > 0) {
      toc.css('visibility', 'visible');
    }
  });
</script>


  <script src=https://lib.baomitu.com/clipboard.js/2.0.10/clipboard.min.js></script>

  <script>Fluid.plugins.codeWidget();</script>


  
<script>
  Fluid.utils.createScript('https://lib.baomitu.com/anchor-js/4.3.1/anchor.min.js', function() {
    window.anchors.options = {
      placement: CONFIG.anchorjs.placement,
      visible  : CONFIG.anchorjs.visible
    };
    if (CONFIG.anchorjs.icon) {
      window.anchors.options.icon = CONFIG.anchorjs.icon;
    }
    var el = (CONFIG.anchorjs.element || 'h1,h2,h3,h4,h5,h6').split(',');
    var res = [];
    for (var item of el) {
      res.push('.markdown-body > ' + item.trim());
    }
    if (CONFIG.anchorjs.placement === 'left') {
      window.anchors.options.class = 'anchorjs-link-left';
    }
    window.anchors.add(res.join(', '));
  });
</script>


  
<script>
  Fluid.utils.createScript('https://lib.baomitu.com/fancybox/3.5.7/jquery.fancybox.min.js', function() {
    Fluid.plugins.fancyBox();
  });
</script>


  <script>Fluid.plugins.imageCaption();</script>

  <script  src="/blog/js/local-search.js" ></script>

  <script defer src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js" ></script>





<!-- 主题的启动项，将它保持在最底部 -->
<!-- the boot of the theme, keep it at the bottom -->
<script  src="/blog/js/boot.js" ></script>


  

  <noscript>
    <div class="noscript-warning">博客在允许 JavaScript 运行的环境下浏览效果更佳</div>
  </noscript>
<script src="/blog/live2dw/lib/L2Dwidget.min.js?094cbace49a39548bed64abff5988b05"></script><script>L2Dwidget.init({"pluginRootPath":"live2dw/","pluginJsPath":"lib/","pluginModelPath":"assets/","tagMode":false,"debug":false,"model":{"jsonPath":"/blog/live2dw/assets/chitose.model.json"},"display":{"position":"right","width":150,"height":300},"mobile":{"show":true},"react":{"opacity":0.7},"log":false});</script></body>
</html>
